package com.xjoyt.pay.gateway.controllers;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xjoyt.pay.commons.ObjectUtils;
import com.xjoyt.pay.commons.PayTypeUtils;
import com.xjoyt.pay.dto.AccessParam;
import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.dto.PageParam;
import com.xjoyt.pay.dto.PageResult;
import com.xjoyt.pay.gateway.annotations.CallbackApi;
import com.xjoyt.pay.gateway.annotations.RestApi;
import com.xjoyt.pay.gateway.constants.RestApiConstant;
import com.xjoyt.pay.gateway.forein.IMainOrderService;
import com.xjoyt.pay.gateway.params.AlipayOrderParam;
import com.xjoyt.pay.gateway.params.AlipayWapPayParam;
import com.xjoyt.pay.gateway.params.BankPayParam;
import com.xjoyt.pay.gateway.params.CallbackParam;
import com.xjoyt.pay.gateway.params.OrderExternalParam;
import com.xjoyt.pay.gateway.params.OrderParam;
import com.xjoyt.pay.gateway.params.ScannedCodeParam;
import com.xjoyt.pay.gateway.params.WechatOrderParam;
import com.xjoyt.pay.gateway.params.WechatWapPayParam;
import com.xjoyt.pay.master.dto.CallbackResult;
import com.xjoyt.pay.master.dto.OrderUrlResult;
import com.xjoyt.pay.master.dto.ScannedCodeResult;
import com.xjoyt.pay.master.interfaces.OrderContract;
import com.xjoyt.pay.master.params.OrderPageParam;
import com.xjoyt.pay.master.po.Distributor;
import com.xjoyt.pay.master.po.Merchant;
import com.xjoyt.pay.master.po.Order;
import com.xjoyt.pay.master.vo.OrderMap;
import com.xjoyt.pay.vo.PayType;

@RestController
@RequestMapping("order")
public class UniOrderController extends GatewayAbstractController
		implements com.xjoyt.pay.gateway.interfaces.OrderContract {

	@Autowired
	private IMainOrderService mainOrderService;
	
	@Value("${gate.jwt.header}")
	private String callbackUrl;

	@PostMapping(path="/uniOrder",name = "统一订单接口")
	public ExecuteResult<String> uniOrder(@RequestBody(required = false) OrderParam param) {
		param.callbackUrl = callbackUrl;
		//根据订单类型选择支付方式
		Integer type = param.payType;
		ExecuteResult<OrderUrlResult> result= null;
		switch (type) {
		case 11://微信刷卡支付
			result = mainOrderService.wechatScan(param);
			break;
		case 12://微信刷卡支付
			
			break;	
		default:
			break;
		}
		
		return result.isSuccess() ? ExecuteResult.ok(result.getValue().url) : ExecuteResult.fail(result.getMessage());
	}
	
	@RestApi(value = RestApiConstant.ORDER_WECHAT_SCAN, name = "微信扫码统一下单")
	@Override
	public ExecuteResult<String> wechatScan(@RequestBody(required = false) AccessParam<OrderParam> param) {
		param.param.merchantId = getMerchant(param.accessToken).id;
		WechatOrderParam p = new WechatOrderParam();
		ObjectUtils.fieldCopy(param.param, p);
		p.callbackUrl = getCallbackUrl();
		ExecuteResult<OrderUrlResult> result = mainOrderService.wechatScan(p);
		return result.isSuccess() ? ExecuteResult.ok(result.getValue().url) : ExecuteResult.fail(result.getMessage());
	}

	@RestApi(value = RestApiConstant.ORDER_ALIPAY_SCAN, name = "支付宝扫码统一下单")
	@Override
	public ExecuteResult<String> alipayScan(@RequestBody(required = false) AccessParam<OrderParam> param) {
		param.param.merchantId = getMerchant(param.accessToken).id;
		AlipayOrderParam p = new AlipayOrderParam();
		ObjectUtils.fieldCopy(param.param, p);
		p.callbackUrl = getCallbackUrl();
		ExecuteResult<OrderUrlResult> result = mainOrderService.alipayScan(p);
		return result.isSuccess() ? ExecuteResult.ok(result.getValue().url) : ExecuteResult.fail(result.getMessage());
	}

	@RestApi(value = RestApiConstant.ORDER_BANK_PAY, name = "网关支付统一下单")
	@Override
	public ExecuteResult<String> bankPay(@RequestBody(required = false) AccessParam<OrderParam> param) {
		param.param.merchantId = getMerchant(param.accessToken).id;
		param.param.callbackSuccessUrl = getCallbackSuccessUrl();
		BankPayParam p = new BankPayParam();
		ObjectUtils.fieldCopy(param.param, p);
		p.callbackUrl = getCallbackUrl();
		ExecuteResult<OrderUrlResult> result = mainOrderService.bankPay(p);
		return result.isSuccess() ? ExecuteResult.ok(result.getValue().url) : ExecuteResult.fail(result.getMessage());
	}

	@RestApi(value = RestApiConstant.ORDER_ALIPAY_WAP, name = "支付宝wap支付统一下单")
	@Override
	public ExecuteResult<String> alipayWapPay(@RequestBody(required = false) AccessParam<OrderParam> param) {
		param.param.merchantId = getMerchant(param.accessToken).id;
		param.param.callbackSuccessUrl = getCallbackSuccessUrl();
		AlipayWapPayParam p = new AlipayWapPayParam();
		ObjectUtils.fieldCopy(param.param, p);
		p.callbackUrl = getCallbackUrl();
		ExecuteResult<OrderUrlResult> result = mainOrderService.alipayWapPay(p);
		return result.isSuccess() ? ExecuteResult.ok(result.getValue().url) : ExecuteResult.fail(result.getMessage());
	}

	@RestApi(value = RestApiConstant.ORDER_WECHAT_WAP, name = "微信wap支付统一下单")
	@Override
	public ExecuteResult<String> wechatWapPay(@RequestBody(required = false) AccessParam<OrderParam> param) {
		param.param.merchantId = getMerchant(param.accessToken).id;
		param.param.callbackSuccessUrl = getCallbackSuccessUrl();
		WechatWapPayParam p = new WechatWapPayParam();
		ObjectUtils.fieldCopy(param.param, p);
		p.callbackUrl = getCallbackUrl();
		ExecuteResult<OrderUrlResult> result = mainOrderService.wechatWapPay(p);
		return result.isSuccess() ? ExecuteResult.ok(result.getValue().url) : ExecuteResult.fail(result.getMessage());
	}

	@RestApi(value = RestApiConstant.ORDER_SCANNED_CODE, name = "被扫码支付统一下单")
	@Override
	public ExecuteResult<ScannedCodeResult> scannedCodePay(
			@RequestBody(required = false) AccessParam<OrderParam> param) {
		param.param.merchantId = getMerchant(param.accessToken).id;
		param.param.callbackSuccessUrl = getCallbackSuccessUrl();
		ScannedCodeParam p = new ScannedCodeParam();
		ObjectUtils.fieldCopy(param.param, p);
		p.callbackUrl = getCallbackUrl();
		ExecuteResult<OrderUrlResult> result = mainOrderService.scannedCodePay(p);
		ScannedCodeResult entity = new ScannedCodeResult();
		if (result.isSuccess()) {
			entity.no = result.getValue().no;
			entity.outTradeNo = result.getValue().outTradeNo;
			entity.money = result.getValue().money;
			return ExecuteResult.ok(entity);
		}
		return ExecuteResult.fail(result.getMessage());
	}

	private String getCallbackUrl() {
		if (isProduct())
			return "https://api.xjockj.com/open/v1/order/callback/";
		if (isDeveloper())
			return getRequestPath() + "/order/callback/";
		return "https://api.open.xjoyt.com/open/v1/order/callback/";
	}

	private String getCallbackSuccessUrl() {
		if (isProduct())
			return "https://api.xjockj.com/open/v1/order/success/";
		if (isDeveloper())
			return getRequestPath() + "/order/success/";
		return "https://api.open.xjoyt.com/open/v1/order/success/";
	}

	/**
	 * 统一回调处理
	 * 
	 * @param param
	 * @return
	 */
	@CallbackApi("下单统一回调")
	@RequestMapping("callback/{id}")
	public String callback(@PathVariable String id, Model model) {
		HttpServletRequest request = getHttpServletRequest();
		StringBuilder body = new StringBuilder();
		try (BufferedReader br = request.getReader()) {
			String str;
			while ((str = br.readLine()) != null) {
				body.append(str);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		CallbackParam param = new CallbackParam();
		param.id = id;
		param.body = body.toString();
		param.params = request.getParameterMap();

		try {
			ExecuteResult<CallbackResult> result = mainOrderService.callback(param);
			CallbackResult callbackResult = result.getValue();
			model.addAttribute("callback", callbackResult);
			model.addAttribute("param", param);
			if (callbackResult != null) {
				model.addAttribute("companyId", callbackResult.companyId);
				model.addAttribute("merchantId", callbackResult.merchantId);
				model.addAttribute("distributorId", callbackResult.distributorId);
				return result.getValue().callbackResponse;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 前台通知
	 * 
	 * @param param
	 * @return
	 */
	@RequestMapping("success/{id}")
	public void success(@PathVariable String id, HttpServletResponse response) {
		Order entity = mainOrderService.get(id);
		if (entity == null || StringUtils.isBlank(entity.successUrl)) {
			return;
		}
		try {
			response.sendRedirect(entity.successUrl);
		} catch (IOException e) {
			e.printStackTrace();
			logger.error("前台通知异常", e);
		}
	}

	@RestApi(value = RestApiConstant.ORDER_GET_BY_NO, name = "获取订单")
	@Override
	public ExecuteResult<com.xjoyt.pay.gateway.params.Order> getByNo(
			@RequestBody(required = false) AccessParam<String> param) {
		Order entity = mainOrderService.getByNo(param.param);
		return ExecuteResult.ok(convert(entity));
	}

	@RestApi(value = RestApiConstant.ORDER_GET_BY_NO, name = "获取订单")
	@Override
	public ExecuteResult<com.xjoyt.pay.gateway.params.Order> getByCustomerNo(
			@RequestBody(required = false) AccessParam<String> param) {
		Order entity = mainOrderService.getByCustomerNo(param.param);
		return ExecuteResult.ok(convert(entity));
	}

	private com.xjoyt.pay.gateway.params.Order convert(Order entity) {
		if (entity == null) {
			return null;
		}
		com.xjoyt.pay.gateway.params.Order result = new com.xjoyt.pay.gateway.params.Order();
		result.no = entity.no;
		result.body = entity.body;
		result.detail = entity.detail;
		result.done = entity.done;
		result.doneDate = entity.doneDate;
		result.merchantNo = entity.merchantNo;
		result.notify = entity.notify;
		result.notifyDate = entity.notifyDate;
		result.successUrl = entity.successUrl;
		result.success = entity.success;
		result.outTradeNo = entity.outTradeNo;
		result.addedDate = entity.addedDate;
		result.money = entity.money;
		result.notifyUrl = entity.notifyUrl;
		return result;
	}

	private com.xjoyt.pay.gateway.params.OrderExternalParam convertOrder(Order entity) {
		if (entity == null) {
			return null;
		}
		com.xjoyt.pay.gateway.params.OrderExternalParam result = new com.xjoyt.pay.gateway.params.OrderExternalParam();
		result.no = entity.no;
		result.body = entity.body;
		result.detail = entity.detail;
		result.done = entity.done;
		result.doneDate = entity.doneDate;
		result.merchantNo = entity.merchantNo;
		result.notify = entity.notify;
		result.notifyDate = entity.notifyDate;
		result.successUrl = entity.successUrl;
		result.success = entity.success;
		result.outTradeNo = entity.outTradeNo;
		result.addedDate = entity.addedDate;
		result.money = entity.money;
		result.notifyUrl = entity.notifyUrl;
		result.payTyp = PayTypeUtils.getName(entity.payType);
		result.tradeNo = entity.tradeNo;
		result.channelName = entity.orderConfig.channelName;
		return result;
	}

	@RestApi(value = RestApiConstant.ORDER_LOAD_PAGE, name = "查询分页订单")
	@Override
	public ExecuteResult<PageResult<com.xjoyt.pay.gateway.params.Order>> loadPage(
			@RequestBody(required = false) AccessParam<PageParam<OrderPageParam>> param) {
		if (param.param == null)
			param.param = new PageParam<>();
		if (param.param.query == null) {
			param.param.query = new OrderPageParam();
		}
		Merchant merchant = getMerchant(param.accessToken);
		if (merchant != null) {
			param.param.query.merchantId = merchant.id;
		}
		Distributor distributor = getDistributor(param.accessToken);
		if (distributor != null) {
			param.param.query.distributorId = distributor.id;
		}
		PageResult<OrderMap> page = mainOrderService.loadPageMap(param.param);
		if (page == null) {
			return ExecuteResult.fail("数据不存在");
		}
		List<com.xjoyt.pay.gateway.params.Order> rows = new ArrayList<>();
		page.forEach(item -> rows.add(convert(item)));
		PageResult<com.xjoyt.pay.gateway.params.Order> result = new PageResult<>(page.getTotal(), rows,
				page.getFooter());
		return ExecuteResult.ok(result);
	}

	@RestApi(value = RestApiConstant.ORDER_PAGE, name = "查询分页订单")
	@Override
	public ExecuteResult<PageResult<OrderExternalParam>> loadOrderPage(
			@RequestBody(required = false) AccessParam<PageParam<OrderPageParam>> param) {
		if (param.param == null)
			param.param = new PageParam<>();
		if (param.param.query == null) {
			param.param.query = new OrderPageParam();
		}
		Merchant merchant = getMerchant(param.accessToken);
		if (merchant != null) {
			param.param.query.merchantId = merchant.id;
		}
		Distributor distributor = getDistributor(param.accessToken);
		if (distributor != null) {
			param.param.query.distributorId = distributor.id;
		}
		PageResult<Order> page = mainOrderService.loadPage(param.param);
		if (page == null) {
			return ExecuteResult.fail("数据不存在");
		}
		List<com.xjoyt.pay.gateway.params.OrderExternalParam> rows = new ArrayList<>();
		page.forEach(item -> rows.add(convertOrder(item)));
		PageResult<com.xjoyt.pay.gateway.params.OrderExternalParam> result = new PageResult<>(page.getTotal(), rows);
		return ExecuteResult.ok(result);
	}

	public void setCallbackUrl(String callbackUrl) {
		this.callbackUrl = callbackUrl;
	}
}
